using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Universe.CrossIO
{
    // 6 chars encode 5 bytes
    public class Base95EncoderStream: Stream
    {
        private long _position;
        byte[] _state = new byte[8];
        private int _pos = 0;
        private Stream _under = null;

        public Base95EncoderStream(Stream under)
        {
            _under = under;
        }

        public override void Flush()
        {
            _under.Flush(); 
        }

        public override void Close()
        {
            if (_pos > 0)
                FlushState();
        }

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return false; }
        }

        public override bool CanWrite
        {
            get { return false; }
        }

        public override long Length
        {
            get { return _position; }
        }

        public override long Position
        {
            get { return _position; }
            set { _position = value; }
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException();
        }

        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            throw new NotSupportedException();
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            for(int i = offset, n = 0; n<count; i++, n++)
            {
                if (_pos == 5)
                    FlushState();

                _state[_pos++] = buffer[i];
            }
        }

        private void FlushState()
        {
            byte[] _buf = new byte[6];
            UInt64 lv = BitConverter.ToUInt64(_state, 0);
            for(int i=0; i<6; i++)
            {
                _buf[i] = (byte) (33 + (int) (lv%95L));
                lv = lv/95;
            }

            _under.Write(_buf, 0, 6);
            _pos = 0;
        }

    }
}
